#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>//htons字节序转换接口
#include<netinet/in.h>//struct sockaddr_in地址结构协议类型头文件
#include<sys/socket.h>//socket套接字接口头文件

int main(int argc,char *argv[]){
    if(argc!=3){
        printf("usage:./udp_srv 127.0.0.1 9000\n");
        return -1;
    }
    char *srv_ip=argv[1];
    uint16_t srv_port=atoi(argv[2]);
    //创建套接字
    int sockfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
    if(sockfd<0){
        perror("socket error");
        return -1;
    }
    //绑定地址信息
    struct sockaddr_in addr;
    addr.sin_family=AF_INET;
    addr.sin_port=htons(srv_port);//主机ip地址转换成网络字节序
    addr.sin_addr.s_addr=inet_addr(srv_ip);//字符串ip地址转换成无符号整型网络字节序ip地址
    socklen_t addrlen=sizeof(struct sockaddr_in);
    int ret=bind(sockfd,(struct sockaddr*)&addr,addrlen);
    if(ret<0){
        perror("bind error");
        return -1;
    }
    while(1){
    //接收数据
    char buf[1024]={0};
    struct sockaddr_in cliaddr;
    socklen_t addrlen=sizeof(struct sockaddr_in);
    ssize_t ret=recvfrom(sockfd,buf,1023,0,(struct sockaddr*)&cliaddr,&addrlen);
    if(ret<0){
        perror("recvfrom error");
        return -1;
    }
    uint16_t cliport=ntohs(cliaddr.sin_port);
    const char* cliip=inet_ntoa(cliaddr.sin_addr);
    printf("client[%s:%d] say:%s\n",cliip,cliport,buf);
    //响应数据
    printf("server say:");
    fflush(stdout);
    fgets(buf,1023,stdin);
    ret=sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&cliaddr,addrlen);
    if(ret<0){
        perror("sendto error");
        return -1;
    }
    }
    //关闭套接字
    close(sockfd);
    return 0;
}
